#!/usr/bin/python3
#import socket
import threading
import base
import richiesta
import rete
#import config
import select
#import sys
#import time
#import traceback
import threaded
#from gi.repository import Gtk
import queue

#classe principale; questa classe è il vero e proprio server
class ServerNonBlocking(threaded.ServerThreaded):
    #questo metodo attiva il ciclo principale del server
    #e per ogni richiesta di connessione attiva un nuovo thread
    #richiede come parametri la dimensione del pacchetto (che può essere cambiata)
    #e il numero massimo di connessioni simultanee che è meglio lasciare così
    def ascolta(self, connessioni = 3):
        #imposta l'indirizzo ip del server e la porta passandolo
        #come una tupla
        connessione = -1
        self.contatore = 0
        self.server.bind(("", self.porta))
        self.server.setblocking(0)
        #imposta il numero massimo di connessioni accettabili simultaneamente
        self.server.listen(connessioni)
        qu = queue.Queue()
        thr = threading.Thread(target = richiesta.threadGestore,args=[qu],name="Gestore")
        thr.daemon = True
        thr.start()
        procedi = -1
        rete.connessioni = []
        rete.datiConnessione = {}
        #questo è il ciclo infinito ossia il cuore del server
        try:
            while True:
                tenta = False
                if not procedi >= 0:
                    r,w,e = select.select(rete.connessioni + [self.server],[],rete.connessioni+ [self.server])
                try:
                    if procedi >= 0:
                        raise base.DatiAvanzatiCondition
                    connessione, indirizzo = self.server.accept()
                    rete.connessioni.append(connessione)
                    datiConn = rete.DatiConn(connessione)
                    print(str(connessione.fileno())+": apertura")
                    rete.datiConnessione[connessione.fileno()] = datiConn
                except BlockingIOError: #nessuna nuova connessione, ci sarà qualcosa da leggere?
                    if len(r) > 0: #magari sì!
                        indiceConnessione = r[0].fileno()
                        datiConn = rete.datiConnessione[indiceConnessione]
                        req = datiConn.req if datiConn.req != None else richiesta.Richiesta(r[0])
                        try:
                            data = r[0].recv(rete.pacchetto)
                            if data == b"": #Se len == 0 è chiusa :) fuori una
                                rete.chiudi(r[0])
                            else:
                                tenta = True
                        except ConnectionResetError:
                            rete.chiudi(r[0])
                except base.DatiAvanzatiCondition:
                    datiConn = rete.datiConnessione[procedi]
                    data = datiConn.datiAvanzati
                    req = procediReq
                    tenta = True
                finally:
                    if tenta:
                        procedi = -1
                        datiConn.metodo, datiConn.datiPrecedenti, datiConn.datiAvanzati = datiConn.metodo(data, req, datiConn.datiPrecedenti,qu)
                        datiConn.req= req
                        if len(datiConn.datiAvanzati) != 0:
                            procedi = indiceConnessione
                            procediReq = req
                    for conn in rete.connessioni + [self.server]:
                        if conn.fileno() < 0 :
                            rete.connessioni.remove(conn)
                #time.sleep(1)
        except KeyboardInterrupt as e:
            print("\n")
        finally:
            for conn in rete.connessioni:
                rete.chiudi(conn)
            rete.chiudi(self.server)
